package modbus_master_connector

import (
	"go-iot-gateway/internal/apk/maths"
	conf_table_define "go-iot-gateway/internal/conf_table/define"
	sys_config "go-iot-gateway/internal/sys/config"
	"go-iot-gateway/pkg/modbus"
	"sync"
	"time"
)

type ModbusRTUConnector struct {
	abstractModbusConnector
	rtuClientHandler *modbus.RTUClientHandler
	protocolInfo     *RTUProtocolInfo
	sendLock         sync.Mutex
}

// "{11B642F4-4D18-4a6b-89F8-B15564BB3EB5}"
func (m *ModbusRTUConnector) _init(protocolConfInfos []*conf_table_define.ProtocolInfo) {
	m.protocolInfo = NewRTUProtocolInfo(protocolConfInfos)

	serialAddrAlias := sys_config.ConfigInfo().SerialAddrAlias
	comName := serialAddrAlias.SerialAddr(m.ChannelInfo.ConnectParams.ComName)
	m.ChannelInfo.ConnectParams.ComName = comName

	m.rtuClientHandler = modbus.NewRTUClientHandler(m.ChannelInfo.ConnectParams.ComName)
	m.rtuClientHandler.SerialParams.BaudRate = int(m.ChannelInfo.ConnectParams.Baud)
	m.rtuClientHandler.SerialParams.DataBits = m.ChannelInfo.ConnectParams.DataBit
	m.rtuClientHandler.SerialParams.Parity = m.ChannelInfo.ConnectParams.CheckBit
	m.rtuClientHandler.SerialParams.StopBits = m.ChannelInfo.ConnectParams.StopBit
	m.rtuClientHandler.SerialParams.ReadTimeout = time.Duration(m.ChannelInfo.ConnectParams.Timeout) * time.Millisecond
	m.rtuClientHandler.SerialParams.SerialName = comName
	m.rtuClientHandler.Logger = m.logger
	//过多久没有请求,将关闭连接。 0 表示从不关闭
	idleTime := maths.MaxInt(m.ChannelInfo.Frequency, m.ChannelInfo.ConnectParams.Timeout)
	m.rtuClientHandler.IdleTimeout = time.Duration(idleTime+7000) * time.Millisecond

	m.modbusClient = modbus.NewClient(m.rtuClientHandler)
}

func (m *ModbusRTUConnector) _connect() error {
	return m.rtuClientHandler.Connect()
}

func (m *ModbusRTUConnector) _close() {
	err := m.rtuClientHandler.Close()
	if err != nil {
		m.logger.Info(err)
	}
}

func (m *ModbusRTUConnector) _numOfRegisterPerFrame() uint16 {
	return m.protocolInfo.NumOfRegisterPerFrame
}

func (m *ModbusRTUConnector) _sendLock() {
	m.sendLock.Lock()
}
func (m *ModbusRTUConnector) _sendUnLock() {
	m.sendLock.Unlock()
}

func (m *ModbusRTUConnector) _writeRetryOnFail() uint8 {
	return m.protocolInfo.WriteRetryOnFail
}
